#include "register.h"

userAddrInfo loginUser[100]; // 保存登录成功用户的地址信息
int users = 0;               // 登录成功的用户数量
userAddrInfo groupMem[100];  // 加入群聊的成员
int groupNum = 0;
int main()
{
    struct sockaddr_in *addr = getSockAddr("192.168.86.132", 9000); // 本地地址转网络地址
    int sd = socket(AF_INET, SOCK_DGRAM, 0);                        // 创建套接字
    int opt = 1;
    setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    if (-1 == bind(sd, (struct sockaddr *)addr, sizeof(struct sockaddr_in))) // 绑定地址
    {
        perror("bind error");
    }
    // 在这下面开始写
    struct sockaddr_in clientAddr;
    socklen_t length = sizeof(clientAddr);
    package pack;
    char buf[128]; // 系统提示消息
    printf("\t\t\e[1;31mW  2  X\e[0m\n");
    printf("------\e[34m服务器------\n\e[0m");
    while (1)
    {
        recvfrom(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, &length);
        if (pack.msgType == REGISTER)
        {
            // 如果注册名字已经存在就注册失败
            printf("\e[33m游客注册信息:\e[0m\n");
            zhuce *info1 = (zhuce *)pack.msgBlock; // 拆开数据包还原
            printf("\e[34mname:%s  tel:%s  pwd:%s\e[0m\n", info1->name, info1->tel, info1->pwd);

            int fd = open("./server_file/userInfo.txt", O_CREAT | O_RDWR | O_APPEND, 0666); // 写入文件
            int flag = 0;
            // 判断是否读到同名
            zhuce info3;
            int ret = read(fd, &info3, sizeof(info3));
            while (ret != 0) // 判断是否到达文件末尾
            {
                if (!strcmp(info3.name, info1->name)) // 名字相同
                {
                    strcpy(buf, "\e[31m注册名字已存在,注册失败\e[0m");
                    puts(buf);
                    memcpy(pack.msgBlock, buf, sizeof(buf));
                    sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                    flag = 1;
                    close(fd);
                    break;
                }
                ret = read(fd, &info3, sizeof(info3));
            }
            if (flag == 0) // 没有重名的
            {
                // 为注册用户在系统创建个人文件夹
                int dir_mode = 0755; // 目录权限
                char dirname[128];
                sprintf(dirname, "./server_file/%s", info1->name);
                if (mkdir(dirname, dir_mode) == -1)
                {
                    if (errno != EEXIST) // 如果创建失败
                    {
                        perror("Failed to create directory A");
                        continue;
                    }
                }
                write(fd, info1, sizeof(zhuce));
                close(fd); //
                strcpy(buf, "\e[1;32m注册成功\e[0m");
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                continue;
            }
        }
        else if (pack.msgType == DENGLU)
        {
            printf("\e[33m游客登录信息:\e[0m\n");
            denglu *info2 = (denglu *)pack.msgBlock;
            printf("\e[34mname:%s  pwd:%s\e[0m\n", info2->name, info2->pwd);
            int fd = open("./server_file/userInfo.txt", O_RDONLY);
            int flag = 0;
            zhuce info3;
            int ret = read(fd, &info3, sizeof(info3));
            while (ret != 0)
            {
                if (!strcmp(info2->name, info3.name)) // 账号正确
                {
                    if (strcmp(info2->pwd, info3.pwd)) // 密码错误
                    {
                        strcpy(buf, "\e[1;31m密码错误\e[0m");
                        puts(buf);
                        flag = 2;
                        memcpy(pack.msgBlock, buf, sizeof(buf));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                        break;
                    }
                    else
                    {
                        int i;
                        // 判断账号是不是已经登录了
                        for (i = 0; i < users; i++)
                        {
                            if (!strcmp(loginUser[i].name, info2->name))
                            {
                                strcpy(buf, "\e[1;31m账号已经被登录了,登陆失败\e[0m");
                                puts(buf);
                                flag = 3;
                                memcpy(pack.msgBlock, buf, sizeof(buf));
                                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                                break;
                            }
                        }
                        if (i >= users)
                        {
                            strcpy(buf, "登录成功");
                            printf("\e[1;32m用户%s%s\e[0m\n", info3.name, buf);
                            strcpy(pack.msgBlock, buf);
                            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                            // 保存下来，用来收发消息，名字和地址绑定起来发送
                            flag = 1;
                            loginUser[users].addr = clientAddr;        // 保存登录用户的地址
                            strcpy(loginUser[users].name, info3.name); // 保存用户名字
                            users++;                                   // 用户数量加一
                            break;
                        }
                    }
                }
                ret = read(fd, &info3, sizeof(info3));
            }
            if (flag == 0)
            {
                strcpy(buf, "\e[1;31m该账号还没有注册\e[0m");
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
            }
            close(fd);
        }
        else if (pack.msgType == SEEKPWD)
        {
            mima mm = *(mima *)pack.msgBlock;
            printf("\e[33m游客找回密码消息:\e[0m\n");
            printf("\e[34mname:%s  tel:%s\e[0m\n", mm.name, mm.tel);
            int fd = open("./server_file/userInfo.txt", O_RDONLY);
            zhuce zc;
            int ret = read(fd, &zc, sizeof(zc));
            int flag = 0;
            while (ret)
            {
                if (!strcmp(zc.name, mm.name)) // 账号一样
                {
                    if (!strcmp(zc.tel, mm.tel)) // 电话号码也一样
                    {
                        flag = 1;
                        char buf[128];
                        sprintf(buf, "\e[34m账号密码是:%s\e[0m", zc.pwd);
                        puts(buf);
                        memcpy(pack.msgBlock, buf, sizeof(buf));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                        break;
                    }
                    else // 电话号码不一样
                    {
                        flag = 2;
                        char buf[128] = "\e[1;31m输入的电话号码错误\e[0m";
                        puts(buf);
                        memcpy(pack.msgBlock, buf, sizeof(buf));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                        break;
                    }
                }
                ret = read(fd, &zc, sizeof(zc));
            }
            if (flag == 0)
            {
                char buf[128] = "\e[1;31m输入的账号未注册\e[0m";
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
            }
            close(fd);
        }
        else if (pack.msgType == XIUGAI)
        {
            newPwd npd = *(newPwd *)pack.msgBlock;
            printf("\e[33m游客的修改账号密码消息:\e[0m\n");
            printf("\e[34mname:%s\toname:%s\tnname:%s\e[0m\n", npd.name, npd.opwd, npd.npwd);
            int fd = open("./server_file/userInfo.txt", O_RDONLY);
            zhuce zh;
            int ret = read(fd, &zh, sizeof(zh));
            zhuce sumInfo[100];
            int num = 0;
            int flag = 0;
            while (ret)
            {
                if (!strcmp(zh.name, npd.name)) // 账号相同
                {
                    if (strcmp(zh.pwd, npd.opwd)) // 账号密码不相等
                    {
                        flag = 1;
                        char buf[128] = "\e[31m账号原密码错误,修改密码失败!\e[0m";
                        puts(buf);
                        memcpy(pack.msgBlock, buf, sizeof(buf));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                        break;
                    }
                    else // 找到要修改的账号
                    {
                        flag = 2;
                        strcpy(zh.pwd, npd.npwd); // 修改原密码
                        sumInfo[num++] = zh;
                    }
                }
                else
                {
                    sumInfo[num++] = zh;
                }
                ret = read(fd, &zh, sizeof(zh));
            }
            close(fd);
            if (flag == 0)
            {
                char buf[128] = "\e[1;31m输入的账号未注册\e[0m";
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
            }
            else if (flag == 2)
            {
                fd = open("./server_file/userInfo.txt", O_TRUNC | O_WRONLY);
                for (int i = 0; i < num; i++)
                {
                    write(fd, &sumInfo[i], sizeof(zhuce));
                }
                close(fd);
                char buf[128] = "\e[31m账号密码修改成功\e[0m";
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
            }
        }
        else if (pack.msgType == ZHUXIAO)
        {
            zhuce np = *(zhuce *)pack.msgBlock;
            printf("\e[33m游客的注销账号消息:\e[0m\n");
            printf("\e[34mname:%s\ttel:%s\tpwd:%s\n\e[0m", np.name, np.tel, np.pwd);
            // 删除该用户在系统的所有文件和痕迹
            int fd = open("./server_file/userInfo.txt", O_RDONLY);
            zhuce zh;
            int ret = read(fd, &zh, sizeof(zh));
            zhuce sumInfo[100];
            int num = 0;
            int flag = 0;
            while (ret)
            {
                if (!strcmp(zh.name, np.name)) // 本人
                {
                    if (strcmp(zh.pwd, np.pwd)) // 密码错误
                    {
                        flag = 1;
                        char buf[128] = "\e[31m密码错误,注销失败\e[0m";
                        puts(buf);
                        memcpy(pack.msgBlock, buf, sizeof(buf));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                        break;
                    }
                    if (strcmp(zh.tel, np.tel))
                    {
                        flag = 1;
                        char buf[128] = "\e[31m电话号码错误,注销失败\e[0m";
                        puts(buf);
                        memcpy(pack.msgBlock, buf, sizeof(buf));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                        break;
                    }
                    flag = 2;
                }
                else
                {
                    sumInfo[num++] = zh;
                }
                ret = read(fd, &zh, sizeof(zh));
            }
            close(fd);
            if (flag == 0)
            {
                char buf[128] = "\e[1;31m输入的账号未注册\e[0m";
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
            }
            else if (flag == 2)
            {
                // 删除服务器为注册用户创建的个人文件夹和里面的文件
                char dirname[128];
                sprintf(dirname, "./server_file/%s", np.name);
                DIR *dp = opendir(dirname);
                struct dirent *mem;
                while ((mem = readdir(dp)) != NULL)
                {

                    if (strcmp(mem->d_name, ".") == 0 || strcmp(mem->d_name, "..") == 0)
                    {
                        continue;
                    }
                    char filename[128];
                    sprintf(filename, "%s/%s", dirname, mem->d_name);
                    remove(filename);
                }
                closedir(dp);
                rmdir(dirname);

                fd = open("./server_file/userInfo.txt", O_TRUNC | O_WRONLY);
                for (int i = 0; i < num; i++)
                {
                    write(fd, &sumInfo[i], sizeof(zhuce));
                }
                close(fd);
                char buf[128] = "\e[31m账号注销成功\e[0m";
                puts(buf);
                memcpy(pack.msgBlock, buf, sizeof(buf));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
            }
        }
        else if (pack.msgType == TUICHU)
        {
            printf("\e[34m游客退出消息:%s\e[0m\n", pack.msgBlock);
            char buf[128] = "\e[1;32m退出成功\e[0m";
            puts(buf);
            memcpy(pack.msgBlock, buf, sizeof(buf));
            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
        }
        else if (pack.msgType == QUNLIAO)
        {
            mtalk mta = *(mtalk *)pack.msgBlock;
            if (mta.type == JIAQUN) // 用户加入群聊
            {
                strcpy(groupMem[groupNum].name, mta.name); // 保存群员名字
                groupMem[groupNum].addr = clientAddr;      // 保存群员地址
                groupNum++;
                // 告诉群员谁加入群聊了
                char buf[128];
                sprintf(buf, "\e[31m%s加入群聊\e[0m", mta.name);
                printf("%s\n", buf);
                strcpy(mta.text, buf);
                memcpy(&pack.msgBlock, &mta, sizeof(mta));
                for (int i = 0; i < groupNum; i++)
                {
                    // 告诉其他群成员谁退出群聊了
                    if (strcmp(mta.name, groupMem[i].name))
                    {
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&groupMem[i].addr, length);
                    }
                }
            }
            else // 用户发送群消息
            {
                if (!strcmp(mta.text, "quit")) // 用户退出群聊，删除群成员
                {
                    char buf[128];
                    sprintf(buf, "\e[31m%s退出群聊\e[0m", mta.name);
                    printf("%s\n", buf);
                    strcpy(mta.text, buf);
                    memcpy(&pack.msgBlock, &mta, sizeof(mta));
                    for (int i = 0; i < groupNum; i++)
                    {
                        // 告诉其他群成员谁退出群聊了
                        if (strcmp(mta.name, groupMem[i].name))
                        {
                            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&groupMem[i].addr, length);
                        }
                    }
                    // 删除它
                    for (int i = 0; i < groupNum; i++)
                    {
                        if (!strcmp(mta.name, groupMem[i].name)) // 找到他
                        {
                            for (int j = i; j < groupNum - 1; j++)
                            {
                                groupMem[j] = groupMem[j + 1];
                            }
                        }
                    }
                    groupNum--; // 数量减一
                }
                else
                {
                    printf("\e[34m%s的群发消息:%s\n\e[0m", mta.name, mta.text);
                    for (int i = 0; i < groupNum; i++)
                    {
                        // 由于名字是唯一的，因此可以通过比较名字来判断是不是自己，不是自己就转发
                        if (strcmp(mta.name, groupMem[i].name))
                        {
                            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&groupMem[i].addr, length);
                        }
                    }
                }
            }
        }
        else if (pack.msgType == APPLY)
        {
            friendApr fri = *(friendApr *)pack.msgBlock;
            if (fri.type == REQUEST)
            {
                printf("\e[31m%s的好友申请消息:请求添加%s为好友\e[0m\n", fri.myname, fri.hisname);
                int i;
                for (i = 0; i < users; i++)
                {
                    if (!strcmp(loginUser[i].name, fri.hisname)) // 找到要添加的好友
                    {
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&loginUser[i].addr, length); // 转发好友申请
                        break;
                    }
                }
                if (i >= users) // 没有找个人
                {
                    sprintf(fri.myname, "\e[31m%s未上线或者不存在,添加失败!\e[0m", fri.hisname);
                    printf("%s\n", fri.myname);
                    fri.type = NOBODY;
                    memcpy(pack.msgBlock, &fri, sizeof(fri));
                    sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
                }
            }
            else if (fri.type == REFUSE)
            {
                printf("\e[31m%s拒绝了%s的好友申请!\e[0m\n", fri.hisname, fri.myname);
                for (int i = 0; i < users; i++)
                {
                    if (!strcmp(loginUser[i].name, fri.myname)) // 找到发好友申请的人
                    {
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&loginUser[i].addr, length); // 转发好友申请
                        break;
                    }
                }
            }
            else if (fri.type == AGREE)
            {
                printf("\e[31m%s同意了%s的好友申请\e[0m\n", fri.hisname, fri.myname);
                // 他把我加入好友列表
                char fileName[128];
                sprintf(fileName, "./server_file/%s/friends.dat", fri.hisname);
                // 创建文件保存用户的好友
                int fd = open(fileName, O_CREAT | O_WRONLY | O_APPEND, 0666);
                friend friInfo;
                strcpy(friInfo.name, fri.myname); // 写入好友名字
                time_t t1;
                time(&t1);
                struct tm *now;
                now = localtime(&t1);
                char nowtime[128];
                sprintf(nowtime, "%d年%d月%d日%d时", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour);
                strcpy(friInfo.time, nowtime);        // 写入时间
                write(fd, &friInfo, sizeof(friInfo)); // 写入文件
                close(fd);
                // 我把他加入好友列表
                sprintf(fileName, "./server_file/%s/friends.dat", fri.myname);
                fd = open(fileName, O_CREAT | O_WRONLY | O_APPEND, 0666);
                strcpy(friInfo.name, fri.hisname);    // 写入好友名字
                strcpy(friInfo.time, nowtime);        // 写入时间
                write(fd, &friInfo, sizeof(friInfo)); // 写入文件
                close(fd);
                for (int i = 0; i < users; i++)
                {
                    if (!strcmp(loginUser[i].name, fri.myname)) // 找到发好友申请的人
                    {
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&loginUser[i].addr, length); // 转发好友申请
                        break;
                    }
                }
            }
        }
        else if (pack.msgType == HAOYOU)
        {
            friendList fli = *(friendList *)pack.msgBlock;
            printf("用户%s查看好友列表\n", fli.name);
            char filename[128];
            sprintf(filename, "./server_file/%s/friends.dat", fli.name);
            int fd = open(filename, O_RDONLY);
            friend fri;
            int ret = read(fd, &fri, sizeof(fri));
            while (ret)
            {
                strcpy(fli.flist[fli.num].name, fri.name);
                int fd2 = open("./server_file/userInfo.txt", O_RDONLY);
                zhuce zh;
                int flag = 0;
                while (read(fd2, &zh, sizeof(zh)))
                {
                    if (!strcmp(zh.name, fri.name))
                    {
                        flag = 1;
                        break;
                    }
                }
                // 判断好友是否在线
                if (flag == 1)
                {
                    int i;
                    for (i = 0; i < users; i++)
                    {
                        if (!strcmp(fri.name, loginUser[i].name))
                        {
                            strcpy(fli.flist[fli.num].isLine, "在线");
                            break;
                        }
                    }
                    if (i >= users)
                    {
                        strcpy(fli.flist[fli.num].isLine, "离线");
                    }
                }
                else
                {
                    strcpy(fli.flist[fli.num].isLine, "注销");
                }
                fli.num++;
                ret = read(fd, &fri, sizeof(fri));
            }
            memcpy(pack.msgBlock, &fli, sizeof(fli));
            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, length);
        }
        else if (pack.msgType == UEXIT)
        {
            printf("\e[31m%s退出登录\e[0m\n", pack.msgBlock);
            // 删除他
            for (int i = 0; i < users; i++)
            {
                if (!strcmp(pack.msgBlock, loginUser[i].name))
                {
                    for (int j = i; j < users - 1; j++)
                    {
                        loginUser[j] = loginUser[j + 1];
                    }
                    break;
                }
            }
            users--;
        }
        else if (pack.msgType == DANLIAO)
        {
            ptalk ptk = *(ptalk *)pack.msgBlock;
            printf("\e[34m%s私发给%s的消息:%s\e[0m\n", ptk.srcname, ptk.desname, ptk.text);
            // 先判断是不是好友
            char fileName[128];
            sprintf(fileName, "./server_file/%s/friends.dat", ptk.srcname);
            int fd = open(fileName, O_RDONLY);
            friend fri;
            int flag = 0;
            int ret = read(fd, &fri, sizeof(fri));
            while (ret)
            {
                if (!strcmp(fri.name, ptk.desname)) // 他是你的好友
                {
                    flag = 1;
                    // 判断好友是否在线
                    for (int i = 0; i < users; i++)
                    {
                        if (!strcmp(ptk.desname, loginUser[i].name)) // 在线
                        {
                            flag = 2;
                            printf("\e[33m%s是%s的好友而且在线,可以私聊\e[0m\n", ptk.desname, ptk.srcname);
                            // 保存聊天记录
                            char filename[128];
                            sprintf(filename, "./server_file/%s/%s.dat", ptk.srcname, ptk.desname);
                            int fd2 = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0666); // 创建聊天记录文件夹
                            ltjr lt;
                            strcpy(lt.name, ptk.srcname); // 谁发的
                            strcpy(lt.text, ptk.text);
                            time_t t1;
                            time(&t1);
                            struct tm *now;
                            now = localtime(&t1);
                            char nowtime[128];
                            sprintf(nowtime, "%d月%d日%d时%d分", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min);
                            strcpy(lt.time, nowtime); // 写入时间
                            write(fd2, &lt, sizeof(lt));
                            close(fd2);
                            sprintf(filename, "./server_file/%s/%s.dat", ptk.desname, ptk.srcname);
                            fd2 = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0666); // 创建聊天记录文件夹
                            write(fd2, &lt, sizeof(lt));
                            close(fd2);
                            //
                            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&loginUser[i].addr, sizeof(struct sockaddr_in));
                            break;
                        }
                    }
                    break;
                }
                ret = read(fd, &fri, sizeof(fri));
            }
            close(fd);
            if (flag != 2)
            {
                ptk.flag = 1;
                char buf[128];
                if (flag == 0)
                {
                    sprintf(buf, "\e[31m%s不是%s的好友,不可以私聊\e[0m", ptk.desname, ptk.srcname);
                }
                else if (flag == 1)
                {
                    sprintf(buf, "\e[31m%s的好友%s不在线,不可以私聊\e[0m", ptk.srcname, ptk.desname);
                }
                puts(buf);
                strcpy(ptk.text, buf);
                memcpy(pack.msgBlock, &ptk, sizeof(ptk));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
                recvfrom(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, &length); // 接收quit但不处理
            }
        }
        else if (pack.msgType == DONGTAI)
        {
            pyq tiez = *(pyq *)pack.msgBlock;
            if (tiez.flag == 0)
            {
                printf("\e[033m%s\e[0m\n", tiez.time);
                printf("\e[34m%s发的朋友圈:%s\e[0m\n", tiez.name, tiez.text);
                char filename[128];
                sprintf(filename, "./server_file/%s/pyq.dat", tiez.name);
                int fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
                write(fd, &tiez, sizeof(tiez));
                close(fd);
                sprintf(filename, "./server_file/%s/friends.dat", tiez.name);
                fd = open(filename, O_RDONLY | O_CREAT, 0666);
                friend fri;
                int ret = read(fd, &fri, sizeof(fri));
                // 应该判断一下好友注销没
                while (ret)
                {
                    int fd3 = open("./server_file/userInfo.txt", O_RDONLY);
                    zhuce zh;
                    int flag = 0;
                    while (read(fd3, &zh, sizeof(zh)))
                    {
                        if (!strcmp(fri.name, zh.name))
                        {
                            flag = 1; // 没有注销
                            break;
                        }
                    }
                    close(fd3);
                    if (flag == 1)
                    {
                        sprintf(filename, "./server_file/%s/pyq.dat", fri.name);
                        int fd2 = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
                        write(fd2, &tiez, sizeof(tiez));
                        close(fd2);
                    }
                    ret = read(fd, &fri, sizeof(fri));
                }
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in)); // 告诉用户发表成功
                close(fd);
            }
            else if (tiez.flag == 1) // 看朋友圈，把朋友圈的系统文件发送给用户
            {
                printf("\e[34m用户%s查看朋友圈\e[0m\n", tiez.name);
                char filename[128];
                sprintf(filename, "./server_file/%s/pyq.dat", tiez.name);
                int fd = open(filename, O_RDONLY); // 打开保存用户朋友圈的服务器文件
                if (fd < 0)                        // 如果没有人发过朋友圈
                {
                    close(fd);
                    strcpy(tiez.text, "你的朋友圈为空");
                    strcpy(tiez.name, "");
                    strcpy(tiez.time, "");
                    tiez.flag = 3; // 告诉客户发完了
                    memcpy(pack.msgBlock, &tiez, sizeof(tiez));
                    sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
                    perror("open fail");
                }
                else
                {
                    while (read(fd, &tiez, sizeof(tiez))) // 取出朋友圈
                    {
                        printf("\e[36m%s\t%s\e[0m\n", tiez.time, tiez.name);
                        printf("  \e[34m%s\n\n\e[0m", tiez.text);
                        tiez.flag = 1; // TMD,我忘了我朋友圈文件里面也有标准位
                        memcpy(pack.msgBlock, &tiez, sizeof(tiez));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
                        usleep(4); // 延时一下，然客户端接收
                    }
                    close(fd);
                    tiez.flag = 2; // 告诉客户发完了
                    memcpy(pack.msgBlock, &tiez, sizeof(tiez));
                    sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
                }

                printf("\e[32m朋友圈发送完毕\n\e[0m");
            }
        }
        else if (pack.msgType == JIRU)
        {
            opjr op1 = *(opjr *)pack.msgBlock;
            if (op1.flag == 1)
            {
                printf("\e[34m用户%s想要查看和%s的聊天记录\e[0m\n", op1.srcname, op1.desname);
                char filename[128];
                sprintf(filename, "./server_file/%s/%s.dat", op1.srcname, op1.desname);
                int fd = open(filename, O_RDONLY);
                ltjr lt;
                while (read(fd, &lt, sizeof(lt)))
                {
                    op1.lt = lt;
                    memcpy(pack.msgBlock, &op1, sizeof(op1));
                    sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
                    usleep(4); // 延时一下，然客户端接收
                }
                op1.isOK = 1; // 告诉用户发完了
                memcpy(pack.msgBlock, &op1, sizeof(op1));
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
            }
            else
            {
                printf("\e[34m用户%s想要清空和%s的聊天记录\e[0m\n", op1.srcname, op1.desname);
                char filename[128];
                sprintf(filename, "./server_file/%s/%s.dat", op1.srcname, op1.desname);
                int fd = open(filename, O_TRUNC); // 清空文件
                close(fd);
                sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
            }
        }
        else if (pack.msgType == CSFILE)
        {
            chuanShou chs = *(chuanShou *)pack.msgBlock;
            if (chs.type == CHUAN)
            {
                printf("\e[34m%s给%s发送了一个文件%s\e[0m\n", chs.srcname, chs.desname, chs.filename);
                // 不检测是不是好友了，没有做离线文件传输了
                char sysfile[128];
                sprintf(sysfile, "./server_file/%s/%s_%s", chs.srcname, chs.desname, chs.filename); // 保存到服务器指定文件夹
                // 给文件添加前缀，区分谁发的，发给谁，什么文件
                int fd = open(sysfile, O_CREAT | O_WRONLY | O_TRUNC, 0666); // 一定要加上0666
                // 如果客户端发送的文件名包含路径信息，服务器可能会尝试在错误的目录下创建文件。
                if (fd < 0)
                {
                    perror("open fail");
                    continue;
                }
                int rcvsize = 0;
                while (1)
                {
                    if (write(fd, chs.data.text, chs.data.bytes) != chs.data.bytes)
                    {
                        perror("write wrong");
                        close(fd);
                        break;
                    }
                    rcvsize += chs.data.bytes;
                    printf("已下载%d个字节\n", rcvsize);
                    if (chs.data.isOK == 1)
                    {
                        close(fd);
                        break;
                    }
                    recvfrom(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, &length);
                    chs = *(chuanShou *)pack.msgBlock;
                }
                printf("下载完毕\n");
                // 告诉客户有人给你发了文件
                for (int i = 0; i < users; i++)
                {
                    if (!strcmp(loginUser[i].name, chs.desname))
                    {
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&loginUser[i].addr, sizeof(struct sockaddr_in));
                    }
                }
            }
            else if (chs.type == SHOU)
            {
                printf("\e[34m%s开始接收%s的文件:%s\n\e[0m", chs.desname, chs.srcname, chs.filename);
                char sysfile[256];
                sprintf(sysfile, "./server_file/%s/%s_%s", chs.srcname, chs.desname, chs.filename); // 服务器读取之前保存的文件
                // puts(sysfile);
                int fd = open(sysfile, O_RDONLY);
                if (fd < 0)
                {
                    // 可以发送给用户，报错
                    perror("open fail");
                    close(fd);
                    continue;
                }
                else
                {
                    struct stat info;
                    stat(sysfile, &info);
                    int leftSize = info.st_size; // 取出传输文件大小文件
                    printf("%d\n", leftSize);
                    int sendSize = 0;
                    while (leftSize)
                    {
                        if (leftSize > 800)
                        {
                            chs.data.isOK = 0;
                            chs.data.bytes = 800;
                        }
                        else
                        {
                            chs.data.isOK = 1; // 告诉客户这是最后一个文件块
                            chs.data.bytes = leftSize;
                        }
                        read(fd, chs.data.text, chs.data.bytes);
                        leftSize -= chs.data.bytes;
                        sendSize += chs.data.bytes;
                        memcpy(pack.msgBlock, &chs, sizeof(chs));
                        sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr_in));
                        printf("已发送%d字节\n", sendSize);
                        usleep(6);
                    }
                    close(fd);
                    printf("\e[32m文件传输完成\e[0m\n");
                    // 在服务器上面删除掉这个文件
                    remove(sysfile); // 用户下载了就删除它
                    for (int i = 0; i < users; i++)
                    {
                        if (!strcmp(loginUser[i].name, chs.srcname))
                        {
                            // 改标志位，区分接收方还是发送方
                            chs.data.isOK = 2; // 发送给发送方，提示你的好友已经接收了文件
                            memcpy(pack.msgBlock, &chs, sizeof(chs));
                            sendto(sd, &pack, sizeof(pack), 0, (struct sockaddr *)&loginUser[i].addr, sizeof(struct sockaddr_in));
                        }
                    }
                }
            }
        }
    }
    close(sd);
}